# -*- coding: utf-8 -*- 

###########################################################################
## Python code generated with wxFormBuilder (version Sep  8 2010)
## http://www.wxformbuilder.org/
##
## PLEASE DO "NOT" EDIT THIS FILE!
###########################################################################

import wx
import os
import ConfigParser
import glob
import webbrowser
import pyHook
import pythoncom

import LnkManageFrame
import LnkManage
import lnkPopWin


_curDir = os.path.abspath(os.path.curdir)
_configFile = os.path.join(_curDir, r'config.ini')
_xmlFileDir = os.path.join(_curDir, r'xml')
_icoFileDir = os.path.join(_curDir, r'ico')
_bmpFileDir = os.path.join(_curDir, r'bmp')

_xmlfile = os.path.join(_curDir, r'Ooooo.xml')

WINTITLE = u"Ooooo"

##########################################################################
key_map = {'1' : '1', '2' : '2', '3' : '3', '4' : '4', '5' : '5',
           '6' : '6', '7' : '7', '8' : '8', '9' : '9', '0' : '0',

           'Q' : 'Q', 'W' : 'W', 'E' : 'E', 'R' : 'R', 'T' : 'T',
           'Y' : 'Y', 'U' : 'U', 'I' : 'I', 'O' : 'O', 'P' : 'P',
           'A' : 'A', 'S' : 'S', 'D' : 'D', 'F' : 'F', 'G' : 'G',
           'H' : 'H', 'J' : 'J', 'K' : 'K', 'L' : 'L',
           'Z' : 'Z', 'X' : 'X', 'C' : 'C', 'V' : 'V', 'B' : 'B', 'N' : 'N', 'M' : 'M',

           'F1' : 'F1', 'F2' : 'F2', 'F3' : 'F3', 'F4' : 'F4', 'F5' : 'F5', 'F6' : 'F6',
           'F7' : 'F7', 'F8' : 'F8', 'F9' : 'F9', 'F10' : 'F10', 'F11' : 'F11', 'F12' : 'F12',

           'Up' : 'Up', 'Down' : 'Down', 'Left' : 'Left', 'Right' : 'Right',

            '[' : 'Oem_4', ']' : 'Oem_6', "'" : 'Oem_5', ';' : 'Oem_1',
            '\'' : 'Oem_7', ',' : 'Oem_Comma', '.' : 'Oem_Period', '/' : 'Oem_2',
           '~' : 'Oem_3', '-' : 'Oem_Minus', '=' : 'Oem_Plus',

           'Left Shift' : 'Lshift', 'Right Shift' : 'Rshift',
           'Left Ctrl' : 'Lcontrol', 'Right Ctrl' : 'Rcontrol',
           'Left Win' : 'Lwin', 'Enter' : 'Return',  'Backspace' : 'Back',
           'Tab' : 'Tab', 'CapsLk' : 'Capital', 'Space' : 'Space', 'Apps' : 'Apps',
           'Esc' : 'Escape', 'PrtSc' : 'Snapshot', 'Delete' : 'Delete',
           'Home' : 'Home', 'End' : 'End', 'Prior' : 'PgUp', 'Next' : 'PgDn'
}

class HotKey():
    """设置热键,组合键是以ALT开始
    比如设置热键为 Alt+Space,那么就是传入Space就可以了
    """
    def __init__(self, frame, hotkey):
        '''frame:父窗口, hotkey:热键字符串'''
        self.hotkey = hotkey
        self.frame = frame
        self.hm = pyHook.HookManager()
        self.hm.KeyDown = self.OnKeyDownEvent
#        hm.KeyUp = self.OnKeyUpEvent
        self.hm.HookKeyboard()
#        import pythoncom
#        pythoncom.PumpMessages()

    def __del__(self):
        self.hm.UnhookKeyboard()
        
    def SetHotKey(self, hotkey):
        self.hotkey = hotkey
        
    def OnKeyUpEvent(self, event):
#        print '---' * 10
#        print 'MessageName:',event.MessageName
#        print 'Message:',event.Message
#        print 'Time:',event.Time
#        print 'Window:',event.Window
#        print 'WindowName:',event.WindowName
#        print 'Ascii:', event.Ascii, chr(event.Ascii)
#        print 'Key:', event.Key
#        print 'KeyID:', event.KeyID
#        print 'ScanCode:', event.ScanCode
#        print 'Extended:', event.Extended
#        print 'Injected:', event.Injected
#        print 'Alt', event.Alt
#        print 'Transition', event.Transition
#        print '---' * 10
        return True

    def OnKeyDownEvent(self, event):
#        print '---' * 10
#        print 'MessageName:',event.MessageName
#        print 'Message:',event.Message
#        print 'Time:',event.Time
#        print 'Window:',event.Window
#        print 'WindowName:',event.WindowName
#        print 'Ascii:', event.Ascii, chr(event.Ascii)
#        print 'Key:', event.Key
#        print 'KeyID:', event.KeyID
#        print 'ScanCode:', event.ScanCode
#        print 'Extended:', event.Extended
#        print 'Injected:', event.Injected
#        print 'Alt', event.Alt
#        print 'Transition', event.Transition
#        print '---' * 10
#        print event.Key
#        print event.Key
        if event.Alt and key_map.has_key(self.hotkey) and  event.Key == key_map[self.hotkey]:
            if self.frame.IsShown():
                self.frame.Hide()
            else:
                self.frame.Show()
            return False
        return True

    
##########################################################################
class OooooTaskBarIcon(wx.TaskBarIcon):
#    TBMENU_Icon1 = wx.NewId()
#    TBMENU_Icon2 = wx.NewId()
    TBMENU_QUIT = wx.NewId()

    def __init__(self, frame):
        wx.TaskBarIcon.__init__(self)
        self.frame = frame

        # Set the image
        icon = wx.Icon(r'ico\search.ico', wx.BITMAP_TYPE_ICO)
        self.SetIcon(icon, 'Ooooo')

        # bind events
        self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
#        self.Bind(wx.EVT_MENU, self.OnTaskBarIcon1, id=self.TBMENU_Icon1)
#        self.Bind(wx.EVT_MENU, self.OnTaskBarIcon2, id=self.TBMENU_Icon2)
        self.Bind(wx.EVT_MENU, self.OnTaskBarQuit, id=self.TBMENU_QUIT)

    def CreatePopupMenu(self):
        menu = wx.Menu()
#        menu.Append(self.TBMENU_Icon1, 'icon1')
#        menu.Append(self.TBMENU_Icon2, 'icon2')
        menu.AppendSeparator()
        menu.Append(self.TBMENU_QUIT, 'Quit')
        return menu

    def OnTaskBarActivate(self, evt):
        if self.frame.IsShown():
            self.frame.Hide()
        else:
            self.frame.Show()

    def OnTaskBarIcon1(self, evt):
        pass
    def OnTaskBarIcon2(self, evt):
        pass
    def OnTaskBarQuit(self, evt):
        self.frame.Destroy()
        self.Destroy()
###########################################################################
class MyFileDropTarget(wx.FileDropTarget):
    """文件拖动处理"""
    def __init__(self, frame):
        wx.FileDropTarget.__init__(self)
        self.frame = frame

    def OnDropFiles(self, x, y, filenames):
        print x, y, filenames
        for file in filenames:
            print file            
            self.frame.lm.addLnk(file)
            self.frame.lm.saveXml(_xmlfile)
            self.LoadXml(_xmlfile)
        
class MyTextDropTarget(wx.TextDropTarget):
    def __init__(self, frame):
        wx.TextDropTarget.__init__(self)
        self.frame = frame
        
    def OnDropText(self, x, y, text):
        print x, y, text
    def OnDragOver(self, x, y, d):
        print x, y, d
        return wx.DragCopy
    
###########################################################################
## Class OooooMainFrame
###########################################################################


class OooooMainFrame ( wx.Frame):
    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = WINTITLE
                            ,pos = wx.DefaultPosition, size = wx.Size( 380,33 )
                            ,style = wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP
                            ,name = WINTITLE )

        self.menuSearchIco = {} # 用于记录菜单id对应的search
        self.searchText = ''    # 记录搜索框输入的内容
        self.popWinFrame = None
        self.defaulthotkey = 'Space'
        self.delta = (0, 0)
        
        self.lnkManageFrame = None

        # 设置热键
        self.hk = HotKey(self, self.defaulthotkey)

        # 用于记录配置信息
        self.winpos = wx.DefaultPosition
        self.lnkdir = ''
        self.Version = ''
        self.searchpath = {}
        self.curSearch = ''
        self.curHotKey = ''
        self.GetConfigFile()
        
        # 创建一个任务栏图标
        try:
            self.tbicon = OooooTaskBarIcon(self)
        except:
            self.tbicon = None

        self.__draw_control()
        
        # 移动窗口到最后一次退出时的位置
        if self.winpos != (-1,-1):
            self.Move(self.winpos)

        self.xmlFils = glob.glob(os.path.join('xml', '*.xml'))

        # 加载lnk目录
        self.lnks = {} # 记录所有的连接
        bmpdir = os.path.join(_curDir, 'bmp')
        self.lm = LnkManage.LnkManage(bmpdir=bmpdir)
        self.LoadXml(_xmlfile)
        self.LoadDirs(None, _xmlfile)
        self.LoadXml(_xmlfile)
        

        #设置文件拖动
        self.fdt = MyFileDropTarget(self)
        self.SetDropTarget(self.fdt)
        
        #self.edt = MyTextDropTarget(self)
        #self.m_searchCtrl.SetDropTarget(self.fdt)
        

    def __draw_control(self):
        pass
        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
        self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_GRAYTEXT ) )
#        self.SetToolTipString( u"Ooooo" ) # 添加这个有点麻烦，关闭程序后，任务管理器里面仍然有进程

        fgSizer = wx.FlexGridSizer( 1, 4, 0, 0 )
        fgSizer.SetFlexibleDirection( wx.BOTH )
        fgSizer.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )

        self.m_bmp_logo = wx.StaticBitmap( self, wx.ID_ANY,
                                           wx.BitmapFromIcon(self.__getCurIco()),
                                           wx.DefaultPosition, wx.DefaultSize, 0 )
        fgSizer.Add( self.m_bmp_logo, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )

        # 添加查找控件
        self.m_searchCtrl = wx.SearchCtrl( self, wx.ID_ANY, wx.EmptyString,
                                           wx.DefaultPosition, wx.Size( 300,-1 ), wx.TE_PROCESS_ENTER)
        self.m_searchCtrl.ShowSearchButton( True )
        self.m_searchCtrl.ShowCancelButton( True )
        self.m_searchCtrl.Bind(wx.EVT_TEXT, self.SearchInfo)
        self.m_searchCtrl.Bind(wx.EVT_TEXT_ENTER, self.searchEnter)
        self.m_searchCtrl.Bind(wx.EVT_KEY_DOWN, self.m_searchCtrlOnKeyDown )
        self.m_searchCtrl.Bind(wx.EVT_KEY_UP, self.m_searchCtrlOnKeyUp )
        self.m_searchCtrl.SetFocus()

        # 添加查找菜单
        searchMenu = wx.Menu()
        for key in self.searchpath.keys():
            value = self.searchpath[key]
            item = searchMenu.AppendRadioItem(-1, value[0])
            self.menuSearchIco[item.GetId()] = key
            iconname = ''
            if value[1]:
                iconname = value[1]
            else:
                iconname = 'define.ico'
            iconpath = os.path.join(_icoFileDir, iconname)

            item.SetBitmap( wx.Bitmap( iconpath, wx.BITMAP_TYPE_ANY ) )
            self.Bind( wx.EVT_MENU, self.menuItemSelect, id = item.GetId() )

        self.m_searchCtrl.SetMenu(searchMenu)
        fgSizer.Add( self.m_searchCtrl, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )

        self.m_bmp_setting = wx.StaticBitmap( self, wx.ID_ANY, wx.Bitmap( u"ico/setting.ico", wx.BITMAP_TYPE_ANY ), wx.DefaultPosition, wx.Size( -1,-1 ), 0 )
        fgSizer.Add( self.m_bmp_setting, 0, wx.ALIGN_CENTER_VERTICAL, 5 )
        
        self.SetSizer( fgSizer )
        self.Layout()
        self.m_menu = wx.Menu()
        self.m_menuItem_lnkmanage = wx.MenuItem( self.m_menu, wx.ID_ANY, u"Lnk&Manage", wx.EmptyString, wx.ITEM_NORMAL )
        self.m_menuItem_close = wx.MenuItem( self.m_menu, wx.ID_ANY, u"&Close", wx.EmptyString, wx.ITEM_NORMAL )
        self.m_menu.AppendItem( self.m_menuItem_lnkmanage )
        self.m_menu.AppendItem( self.m_menuItem_close )


        self.Bind(wx.EVT_MENU, self.ClosePopWin, self.m_menuItem_close)
        self.Bind(wx.EVT_MENU, self.ShowLnkManageWin, self.m_menuItem_lnkmanage)
        
        
        self.Centre( wx.BOTH )
        
        # Connect Events
        self.m_bmp_setting.Bind( wx.EVT_LEFT_DOWN, self.OnLeftDown )
        self.m_bmp_setting.Bind( wx.EVT_LEFT_UP, self.OnLeftUp )
        self.m_bmp_setting.Bind( wx.EVT_MOTION, self.OnMouseMove )
        self.m_bmp_setting.Bind( wx.EVT_RIGHT_DOWN, self.OooooMainFrameOnContextMenu )
#        self.Bind( wx.EVT_RIGHT_UP, self.OnRightUp )
#        self.Bind( wx.EVT_KILL_FOCUS, self.OnKillFocus)
#        self.Bind( wx.EVT_SET_FOCUS, self.OnSetFocus )

    def __getCurIco(self):
        iconame = ''
        if self.searchpath[self.curSearch][1]:
            iconame = self.searchpath[self.curSearch][1]
        else:
            iconame = 'define.ico'
        self.cursearchico = os.path.join(_icoFileDir, iconame)
        return wx.Icon(self.cursearchico, wx.BITMAP_TYPE_ICO, 16, 16)

    def SetSearchEditDefineText(self):
        '''设置没有任何输入时搜索框的内容
        '''
        if self.searchText == '':
            self.m_searchCtrl.Value = self.searchpath[self.curSearch][0]
            self.m_searchCtrl.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, wx.FONTSTYLE_SLANT, 90, False, wx.EmptyString ) )

    def menuItemSelect(self, event):
        self.curSearch = self.menuSearchIco[event.Id]
        self.m_bmp_logo.SetIcon(self.__getCurIco())
        self.SetSearchEditDefineText()
        
    def ClosePopWin(self, event):
        self.SetConfigFile()
        if self.tbicon is not None:
            self.tbicon.Destroy()
        self.Destroy()
        
    def ShowLnkManageWin(self, event):
        self.lnkManageFrame = LnkManageFrame.LnkManage(self)
        self.lnkManageFrame.Show()
        pass

    def __del__( self ):
        if self.tbicon:
            self.tbicon.Destroy()
            self.tbicon = None
        if self.lnkManageFrame:
            self.lnkManageFrame.Destroy()
            self.lnkManageFrame = None
        if self.popWinFrame:
            self.popWinFrame.Destroy()
            self.popWinFrame = None
        self.Close()
        pass
    
    
    # Virtual event handlers, overide them in your derived class
#    def OnKillFocus(self, event):
##        print 'KillFocus'
#        self.Hide()
#
#    def OnSetFocus(self, event):
##        print 'SetFocus'
#        pass

    def OnLeftDown( self, event ):
#        print "down"
        self.m_bmp_setting.CaptureMouse()
        x, y = self.ClientToScreen(event.GetPosition())
        originx, originy = self.GetPosition()
        dx = x - originx
        dy = y - originy
        self.delta = ((dx, dy))
    
    def OnLeftUp( self, event ):
#        print 'up'
        if self.m_bmp_setting.HasCapture():
            self.m_bmp_setting.ReleaseMouse()
    
    def OnMouseMove( self, event ):
#        print 'move'
        if event.Dragging() and event.LeftIsDown() and self.delta != (0, 0) :
            x, y = self.ClientToScreen(event.GetPosition())
            fp = (x - self.delta[0], y - self.delta[1])
            self.Move(fp)
    
#    def OnRightUp( self, event ):
#        event.Skip()
    
    def OooooMainFrameOnContextMenu( self, event ):
        self.m_bmp_setting.PopupMenu( self.m_menu, event.GetPosition() )

    def GetConfigFile(self):
        self.config = ConfigParser.SafeConfigParser()
        self.config.read(_configFile)
        if self.config.has_option('win', 'hotkey'):
            self.curHotKey = self.config.get('win', 'hotkey')
            self.hk.SetHotKey(self.curHotKey)
        if self.config.has_option('win', 'pos'):
            posstr = self.config.get('win', 'pos').split(',')
            self.winpos = (int(posstr[0]), int(posstr[1]))
        if self.config.has_option('win', 'cursearch'):
            self.curSearch = self.config.get('win', 'cursearch')
        if self.config.has_option('lnkmanage', 'dir'):
            self.lnkdir = self.config.get('lnkmanage', 'dir').decode('gbk')
        if self.config.has_option('main', 'Version'):
            self.Version = self.config.get('main', 'Version').decode('gbk')
        if self.config.has_section('search'):
            for item in self.config.items('search'):
                self.searchpath[item[0]] = item[1].split(',')

    def SetConfigFile(self):
        self.winpos = self.GetPosition()
#        print 'set win pos ' + str(self.winpos)[1:-1]
        self.config.set('win', 'pos', str(self.winpos)[1:-1])
        self.config.set('win', 'hotkey', self.curHotKey)
        fp = open(_configFile, 'w')
        self.config.write(fp)
        fp.close()

    def LoadXml(self, xmlfile):
        if os.path.exists(xmlfile):
            self.lm.loadXml(xmlfile)
            
    def LoadDirs(self, dirs, savefile):
        '''加载配置文件中的dir'''    
        ret = True
        if dirs == None:
            dirs = self.lnkdir
        
        for dir in dirs.split(','):
            if dir == '' or not os.path.exists(dir): 
                continue
            r = self.lm.addLnk(dir)
            if not ret:
                ret = r
                
        if ret == True:
            self.lm.createXml()
            self.lm.saveXml(savefile)
            

    def searchEnter(self, evt):
        # 要想响应编辑栏回车键，需要开启style:wx.TE_PROCESS_ENTER
        self.searchUrl = self.searchpath[self.curSearch][2]
        rect = self.GetRect()
        value = self.m_searchCtrl.GetValue()
        if value and value[0] == ';' and len(value) > 1:
            if self.popWinFrame != None:
                dictLnk = self.lm.FindLnk(value[1:])
                self.popWinFrame.UpdateLnk(dictLnk, rect=rect)
            else:
                self.popWinFrame = lnkPopWin.lnkPopWin(self,
                                                 lnkdict=self.lm.FindLnk(value[1:]),
                                                 rect=rect)
            self.popWinFrame.Show()
            self.m_searchCtrl.SetFocus()
        else:
            url = self.searchUrl.replace('%s', value)
            webbrowser.open(url)

    def SearchInfo(self, evt):
        value = self.m_searchCtrl.GetValue()
        self.searchText = value
        if value and value[0] == ';' and len(value) > 1:
            pass

    def m_searchCtrlOnKeyDown(self, event):
        pass
    def m_searchCtrlOnKeyUp(self, event):
        pass
    
    def LoadLnkXmlFile(self, xmlfile):
        self.lm.loadXml(xmlfile)
        
        pass
    
    
    
if __name__ == '__main__':
    try:
        # 首先查找该程序是否已经运行
        win = win32ui.FindWindow(None, 'Ooooo')
        try:
            if win:
                win.ShowWindow(win32con.SW_SHOWNORMAL)
        except:
            pass
    except:
        # 没有找到相关窗口
        app = wx.App()
        main_frm = OooooMainFrame(None)
    
        main_frm.Show()
        app.MainLoop()
